﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ArmyBuilder_Modele;
using ArmyBuilder_DAO;

namespace ArmeeBuilder_Metier
{
    /// <summary>
    /// Classe abstraite définissant un objet de l'application
    /// </summary>
    abstract public class ObjectMetier<I,M,D> : IObjectModele<I> where I:IObjectModele<I> where M:ObjectMetier<I,M,D>,I,new() where D:Data<I,M>,new()
    {
    #region Attributs

        static private D m_oData;
        public string strNom { get; set; }

    #endregion
    #region Propriétés

        static protected D oData
        {
            get
            {
                if( m_oData == null )
                    m_oData = new D();

                return m_oData;
            }            
        }

        
        public string Code
        {
            get
            {
                return strNom;
            }
        }

    #endregion
    #region Fonctions Base

        public virtual void Initialise( string strNom )
        {
            this.strNom = strNom;
        }

        abstract public void CopyTo( I oDest );
       
        public I Clone()
        {
            I oClone = new M();
            this.CopyTo(oClone);
            return oClone;
        }

        override public string ToString()
        {
            return string.Format("Object infos : Nom :{0}", strNom);
        }

    #endregion
    #region Fonction Data

        public static List<I> List() 
        {           
            return oData.List();
        }

        public static I Find(string strCode) 
        {           
            return (I)oData.Find(strCode);
        }
        
    #endregion   
    }

    /// <summary>
    /// Classe définissant une armée
    /// </summary>
    public class Armee : ObjectMetier<IArmeeModele, Armee, ArmeeData<Armee>>, IArmeeModele
    {
    #region Attribut
        public IRaceModele oRace
        {
            get;
            set;
        }
    #endregion
    #region Constructeur

        public Armee()            
        {
            oRace = new Race();
        }

        public Armee(string strNom, IRaceModele oRace)
            : this()
        {
            Initialise(strNom);
        }

        public Armee(IArmeeModele oSrc)
            : this()
        {
            oSrc.CopyTo(this);
        }

    #endregion
    #region Fonction base

        public void Initialise(string strNom, IRaceModele oRace)
        {
            base.Initialise(strNom);

            oRace.CopyTo(this.oRace);
        }

        override public void CopyTo(IArmeeModele oDest)
        {
            oDest.Initialise(this.strNom);
        }

        static public void ImportArmee()
        {
            oData.ImportInfoArmee();
        }

        public override string ToString()
        {
            return string.Format(   @"Armee infos : 
                                        Nom :{0}
                                        {1}",
                                    strNom, oRace.ToString());
        } 

    #endregion
    }    

    /// <summary>
    /// Classe métier d'une race d'armée
    /// </summary>
    public class Race : ObjectMetier<IRaceModele, Race,RaceData<Race>>, IRaceModele
    {     
    #region Attribut

    #endregion
    #region Constructeur    
    
        public Race(){}       

        public Race( string strNom ):this()
        {            
            Initialise( strNom );
        }

        public Race( IRaceModele oSrc ):this()
        {
            oSrc.CopyTo( this );
        }

    #endregion
    #region Fonction base

        override public void CopyTo( IRaceModele oDest )
        {
            oDest.Initialise( this.strNom );
        }

        public override string ToString()
        {
            return string.Format("Race infos : Nom :{0}", strNom);
        }        

    #endregion   
    }  

    /// <summary>
    /// Classe métier d'une catégorie d'unité
    /// </summary>
    public class Categorie : ObjectMetier<ICategorieModele, Categorie,CategorieData<Categorie>>, ICategorieModele
    {   
    #region Attribut

    #endregion
    #region Constructeur

        public Categorie(){}

        public Categorie( string strNom ):this()
        {
            Initialise( strNom );
        }

        public Categorie( ICategorieModele oSrc ):this()
        {
            oSrc.CopyTo( this );
        }

    #endregion
    #region Fonction base

        override public void CopyTo( ICategorieModele oDest )
        {
            oDest.Initialise( this.strNom );
        }

        public override string ToString()
        {
            return string.Format("Categorie infos : Nom :{0}", strNom);
        } 

    #endregion
    #region Fonction info

    #endregion
    }

    /// <summary>
    /// Classe définissant une unité
    /// </summary>
    public class Unite : ObjectMetier<IUniteModele, Unite,UniteData<Unite>>, IUniteModele
    {     

    #region Attribut
        
        public string   strRace             {get;set;}
        public string   strCategorie        {get;set;}
        public int      nNbPoint            {get;set;}
        public int      nTaille             {get;set;}        
        public bool     bMinMaxTaille       {get;set;}

        private List<IFigurineModele> m_listUnite;
        public List<IFigurineModele> listFigurine
        { 
            get
            {
                return m_listUnite;
            }
        }        

    #endregion
    #region Constructeur

        public Unite()
        {
            m_listUnite = new List<IFigurineModele>();
        }

        public Unite(string strNom, string strRace, string strCategorie, List<IFigurineModele> listFigurine):this()
        {
            Initialise(strNom, strRace, strCategorie, nNbPoint, nTaille, bMinMaxTaille, listFigurine);
        }

        public Unite( IUniteModele oSource ):this()
        {
            oSource.CopyTo(this);
        }

    #endregion
    #region Fonction base
       
        public void Initialise(string strNom, string strRace, string strCategorie, int nNbPoint, int nTaille, bool bMinMaxTaille, List<IFigurineModele> listFigurine)
        {
            this.strNom         = strNom;
            this.strRace        = strRace;
            this.strCategorie   = strCategorie;
            this.nNbPoint       = nNbPoint;
            this.nTaille        = nTaille;
            this.m_listUnite    = new List<IFigurineModele>(listFigurine);
        }

        override public void CopyTo( IUniteModele oDest )
        {
            oDest.Initialise( this.strNom, this.strRace, this.strCategorie, this.nNbPoint, this.nTaille, this.bMinMaxTaille, this.listFigurine );
        }  
         
    #endregion
    #region Fonction data

        public static List<IUniteModele> GetListUnite(string strCodeRace, string strCodeCategorie)
        {
            return oData.GetListUnite(strCodeRace, strCodeCategorie);
        }

    #endregion
    }

    /// <summary>
    /// Classe définissant une figurine
    /// </summary>
    public class Figurine : ObjectMetier<IFigurineModele, Figurine,FigurineData<Figurine>>, IFigurineModele
    {     

    #region Attribut
        
        public int      nM     {get;set;}
        public int      nCC    {get;set;}
        public int      nCT    {get;set;}
        public int      nF     {get;set;}
        public int      nE     {get;set;}
        public int      nPV    {get;set;}
        public int      nI     {get;set;}
        public int      nA     {get;set;}
        public int      nCD    {get;set;}
        public ITypeFigurineModele oType{get;set;}

    #endregion   
    #region Cobnstructeur
        
        public Figurine(){}

        public Figurine(string strNom):this()
        {
            Initialise(strNom);
        }    

        public Figurine( IFigurineModele oSrc ):this()
        {
            oSrc.CopyTo(this);
        }
    #endregion
    #region Fonction base
        
        override public void CopyTo( IFigurineModele oDest )
        {
            oDest.Initialise( this.strNom );
        } 

    #endregion
    }
    
    /// <summary>
    /// Classe métier d'un type de figurine
    /// </summary>
    public class TypeFigurine : ObjectMetier<ITypeFigurineModele, TypeFigurine,TypeFigurineData<TypeFigurine>>, ITypeFigurineModele
    {     
      
    #region Attribut
        
    #endregion
    #region Constructeur    
    
        public TypeFigurine(){}       

        public TypeFigurine( string strNom ):this()
        {            
            Initialise( strNom );
        }

        public TypeFigurine( ITypeFigurineModele oSrc ):this()
        {
            oSrc.CopyTo(this);
        }

    #endregion
    #region Fonction base        

        override public void CopyTo( ITypeFigurineModele oDest )
        {
            oDest.Initialise( this.strNom );
        }

    #endregion   
    }  
    
    /// <summary>
    /// Classe métier d'un élément de figurine
    /// </summary>    
    abstract public class EltUnite<I,M,D> : ObjectMetier<I, M, D>, IEltUniteModele<I> where I:IEltUniteModele<I> where M:EltUnite<I,M,D>,I,new() where D:EltUniteData<I,M>,new()
    {     
    #region Attribut
        
        public string strDescription   {get;set;}        

    #endregion
    #region Constructeur
        
    #endregion
    #region Fonction base        

        public void Initialise( string strNom, string strDescription )
        {
            this.strNom = strNom;
        }

        //abstract public void CopyTo( I oDest );

    #endregion   
    } 

    /// <summary>
    /// Classe métier d'équipement d'unité
    /// </summary>
    public class Equipement : EltUnite<IEquipementModele, Equipement,EquipementData<Equipement>>, IEquipementModele
    {         
    #region Fonction base

        override public void CopyTo( IEquipementModele oDest )
        {
           oDest.Initialise( this.strNom, this.strDescription );
        }       

    #endregion
    }   
}
